﻿using Infrastructure.Contracts;
using System;
using System.ComponentModel;
using System.IO;

namespace Infrastructure.Assists
{
    /// <summary>
    /// 无线程文件下载
    /// 有需要的话可在外部实现异步线程
    /// 使用方法见单元测试
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class FileDownload<T> where T : FileTransferProtocol
    {
        public event ProgressChangedEventHandler OnProgressChanged = delegate { };
        public event AsyncCompletedEventHandler OnCompleted = delegate { };

        public void Go<ISvc>(string domain_code, T info) where ISvc : IFileDownloadContract
        {
            FileTransferProtocol _fileInfo = info;

            MemoryStream fs = new MemoryStream();

            try
            {
                ServiceCaller.TcpServiceDispatcher<ISvc>((client) =>
                {
                    try
                    {
                        int maxSiz = 1024 * 100;
                        // 根据文件名获取服务器上的文件  

                        _fileInfo = client.GetFileInfo(_fileInfo);

                        while (_fileInfo.Length != _fileInfo.OffSet)
                        {
                            _fileInfo.Buffer = new byte[_fileInfo.Length - _fileInfo.OffSet <= maxSiz ?
                                _fileInfo.Length - _fileInfo.OffSet :
                                maxSiz]; //设置传递的数据的大小  
                            _fileInfo.OffSet = fs.Length;//设置本地文件数据的读取位置  
                            _fileInfo = client.DownloadFile(_fileInfo);

                            fs.Write(_fileInfo.Buffer, 0, _fileInfo.Buffer.Length);

                            int percent = (int)(((double)_fileInfo.OffSet / (double)((long)_fileInfo.Length)) * 100);
                            OnProgressChanged(this, new ProgressChangedEventArgs(percent, null));
                        }

                        _fileInfo.Buffer = fs.ToArray();

                        OnCompleted(this, new AsyncCompletedEventArgs(null, false, _fileInfo));

                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        fs.Close();
                        fs.Dispose();
                    }
                });
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                    _fileInfo.Msg = ex.InnerException.Message;
                else
                    _fileInfo.Msg = ex.Message;
                OnCompleted(this, new AsyncCompletedEventArgs(null, false, _fileInfo));
            }
        }
    }


    public class FileUpload<T> where T : FileTransferProtocol
    {
        public event ProgressChangedEventHandler OnProgressChanged = delegate { };
        public event AsyncCompletedEventHandler OnCompleted = delegate { };

        public void Go<ISvc>(string domain_code, T info) where ISvc : IFileUploadContract
        {
            FileTransferProtocol fileInfo = info;

            byte[] newbytes = new byte[fileInfo.Buffer.Length];

            fileInfo.Buffer.CopyTo(newbytes, 0);

            MemoryStream ms = new MemoryStream(newbytes);

            try
            {
                ServiceCaller.TcpServiceDispatcher<ISvc>((client) =>
                {
                    try
                    {
                        int maxSiz = 1024 * 100;
                        fileInfo.OffSet = 0;
                        while (fileInfo.Length > fileInfo.OffSet)
                        {
                            fileInfo.Buffer = new byte[fileInfo.Length - fileInfo.OffSet <= maxSiz ? fileInfo.Length - fileInfo.OffSet : maxSiz]; //设置传递的数据的大小  

                            ms.Seek(fileInfo.OffSet, SeekOrigin.Begin);
                            ms.Read(fileInfo.Buffer, 0, fileInfo.Buffer.Length);//把数据写入到file.FileByte中  

                            fileInfo = client.UploadFile(fileInfo);

                            int percent = (int)(((double)fileInfo.OffSet / (double)((long)fileInfo.Length)) * 100);
                            OnProgressChanged(this, new ProgressChangedEventArgs(percent, null));
                        }

                        OnCompleted(this, new AsyncCompletedEventArgs(null, false, fileInfo));
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        ms.Close();
                        ms.Dispose();
                    }
                });
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                    fileInfo.Msg = ex.InnerException.Message;
                else
                    fileInfo.Msg = ex.Message;

                OnCompleted(this, new AsyncCompletedEventArgs(null, false, fileInfo));
            }
        }
    }
}
